package cn.iocoder.yudao.framework.util;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * <pre>
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 *  这里是文件说明
 * OOoO0OOoO0OOOooo0oOOOO0OOOOO0oooOO0ooOOO0Ooooo0OOOOo0ooooO0OOooo0Ooooo0OOOOO
 * </pre>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @since 2025/04/07
 */
@UtilityClass
@Slf4j
public class ObjectUtils {

    public static <T> boolean equals(T source, T target) {
        if (source == target) {
            return true;
        }
        if (source instanceof Number && target instanceof Number) {
            return NumberUtil.equals((Number) source, (Number) target);
        }
        if (source == null || target == null) {
            return false;
        }
        if (source.getClass() != target.getClass() && !(source instanceof Map && target instanceof Map)) {
            // 根据equals设计原则，类型不一致，直接false（仅允许HashMap、LinkedHashMap的差异）
            // 避免子类与父类、子类与子类比较时可能出现的问题
            log.warn("source: {} 和 target: {} 类型不匹配", source.getClass(), target.getClass());
            return false;
        }
        if (source instanceof Class) {
            return ((Class<?>) source).getName().equals(((Class<?>) target).getName());
        }
        if (source instanceof Comparable) {
            // 部分java早期类的equals和compareTo结果不一致，避免直接调用equals
            //noinspection unchecked
            return ((Comparable<T>) source).compareTo(target) == 0;
        }
        if (source instanceof Collection<?> sourceList) {
            Collection<?> targetList = (Collection<?>) target;
            // size不等
            if (sourceList.size() != targetList.size()) {
                return false;
            } else if (sourceList.isEmpty()) {
                // size相等，且一个为空集合
                return true;
            }
            if (source instanceof Set) {
                //noinspection SuspiciousMethodCalls
                return ((Set<?>) source).containsAll(targetList);
            }
            // 分别统计 Collection中 元素对应的数量
            return CollectionUtils.isEqualCollection(sourceList, targetList);
        }
        if (source instanceof Map<?, ?> sourceMap) {
            Map<?, ?> targetMap = (Map<?, ?>) target;
            if (sourceMap.size() != targetMap.size()) {
                return false;
            } else if (sourceMap.isEmpty()) {
                return true;
            }
            for (Map.Entry<?, ?> entry : sourceMap.entrySet()) {
                if (!equals(entry.getValue(), targetMap.get(entry.getKey()))) {
                    return false;
                }
            }
            return true;
        }
        log.warn("暂未实现类型 {} - {} 的比对！", source.getClass().getName(), target.getClass().getName());
        return false;
    }

    @SafeVarargs
    public static <T> boolean anyEquals(T source, T... others) {
        if (others == null) {
            return false;
        }
        for (T other : others) {
            if (equals(source, other)) {
                return true;
            }
        }
        return false;
    }

    public static boolean isAnyEmpty(Object... objs) {
        if (objs == null || objs.length == 0) {
            return true;
        }
        for (Object obj : objs) {
            if (ObjectUtil.isEmpty(obj)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 全都不为空则返回true
     *
     * @param objs objs
     * @return true/false
     */
    public static boolean isNoneEmpty(Object... objs) {
        return !isAnyEmpty(objs);
    }

    /**
     * 全为空则返回true
     *
     * @param objs objs
     * @return true/false
     */
    public static boolean isAllEmpty(Object... objs) {
        if (ObjectUtil.isEmpty(objs)) {
            return true;
        }
        for (Object obj : objs) {
            if (ObjectUtil.isNotEmpty(obj)) {
                return false;
            }
        }
        return true;
    }

    public static boolean isFuzzyTrue(Object target) {
        return List.of("true", "是", "对", "y", "yes", "1", "√").contains(target.toString().toLowerCase());
    }

}
